//
// Created by sxt on 2023/10/18.
//

#include <TypeDescriptor.h>
#include <MyException.h>

namespace myreflect {

    const string &TypeDescriptor::getClassName() const {
        return className;
    }

    const vector<Field> &TypeDescriptor::getDeclaredFields() const {
        return fields;
    }

    const vector<Method> &TypeDescriptor::getDeclaredMethods() const {
        return methods;
    }

    Field TypeDescriptor::getField(const string &name) const {
        for (auto &item: fields) {
            if (item.getFieldName() == name) {
                return item;
            }
        }
        throw FieldNotFoundException(name + "属性不存在");
    }

    Method TypeDescriptor::getMethod(const string &name) const {
        for (auto &item: methods) {
            if (item.getMethodName() == name) {
                return item;
            }
        }
        throw MethodNotFoundException(name + "方法不存在");
    }

    void* TypeDescriptor::newInstance() {
        return createObjMethod();
    }

    RawTypeDescriptorBuilder::~RawTypeDescriptorBuilder() {
        Registry::instance().registerClass(std::move(typeDescriptor));
    }

    RawTypeDescriptorBuilder::RawTypeDescriptorBuilder(const string &name, void *(createObj)()) : typeDescriptor(
            make_unique<TypeDescriptor>()) {
        typeDescriptor->className = name;
        typeDescriptor->createObjMethod = createObj;
    }

    Registry &Registry::instance() {
        static Registry registry;
        return registry;
    }

    TypeDescriptor *Registry::findClass(const string &name) {
        auto found = typeMaps.find(name);
        if (found != typeMaps.end()) {
            return found->second.get();
        }
        return nullptr;
    }

    void Registry::registerClass(unique_ptr<TypeDescriptor> typeDesc) {
        auto name = typeDesc->getClassName();
        typeMaps[name] = std::move(typeDesc);
    }

    TypeDescriptor &getClassByName(const string &name) {
        auto cls = Registry::instance().findClass(name);
        if (cls == nullptr) {
            throw ClassNotFoundException(name + "类不存在");
        }
        return *cls;
    }
}
